//第六章 面向对象
console.log('------------第六章 面向对象-----------')
//复习下冒泡排序
function bubble(arr) {
    var len = arr.length;
    for (let i = 0; i < len-1; i++) {
        for (let j = 0; j < len -i -1; j++) {
            if (arr[j] > arr[j+1]) {
                arr[j] = arr[j] + arr[j+1];
                arr[j+1] = arr[j] - arr[j+1];
                arr[j] = arr[j] - arr[j+1];
            }
            
        }
        
    }
}
/*
var arr = [10,2,4,3,6,7,1,8];
bubble(arr);
console.log(arr);
*/

//对象的数据属性
/*
 configurable(能否通过delete删除属性默认true)、
 enumerable(能否通过for-in 默认true)、
 writable(是否可写 默认true) 
 value(设置属性的值默认undefined)
 get 默认是undefined 提供一个函数实现getter
 set 默认是undefined 提供一个函数实现setter
 
 */

 var obj = {};
 //给obj对象设置一个属性name其值为kongfu 并且为不可写(只读属性)
 Object.defineProperty(obj,'name',{writable:false,value:'kongfu'}); //定义一个属性
 Object.defineProperties(obj,{
     from:{
     writable:false,
     value:"广东"
    },
    address:{
        value:"广州天河区"
    }
}) //定义多个属性
 obj.name = 'zhou'; //严格模式会报错 但是属性值不会改变
console.log(obj);
//读取特性
var descriptor = Object.getOwnPropertyDescriptor(obj,'from');
console.log(descriptor);

//----------------- 创建类 --------------

function Person(name,age,job) {
    this.name = name;
    this.age = age;
    this.job = job;
    //定义在内部的函数，会导致每创建一个对象都会重新创建一个一样功能的函数占用内存
    this.sayHello = function () {
        console.log("Hello "+this.name+' '+this.job);
    };
}
var p1 = new Person('Lee',29,'产品专员');
console.log('p1.constructor=',p1.constructor.name); //获取构造函数的函数名
if (p1 instanceof Person) {
    console.log("是Person对象..");
}
//把类的构造函数当前函数来用

Person("godden",30,'经理'); //执行函数 该函数的所有属性绑定到window对象了
window.sayHello();
console.log(window.name)

//绑定到其他作用域
var obj = {};
Person.call(obj,'saving',31,'行政专员');
obj.sayHello();

//原型链创建类,这样所有实例共享一个对象的属性

function Student() {
    
}
var s0 = new Student(); //该实例的原型链依然指向原来的原型链

//重新定义原型链
Student.prototype = {
    school:'广州一中',
    construtor:Student, //如果不设置那么 construtor 会指向 Object 构造函数
    getStuCount:function (){
        return 100;
    }
}

var s1 = new Student()
console.log('s1.school=',s1.school);
console.log(s1.constructor.name)

//理解原型链
// p1.hasOwnProperty('name') 该方法只能判断实例的属性 不能判断原型链的属性
// 'name' in p1 不管实例还是原型链 只要有该属性就会返回true
console.log('name' in p1);

//6.2.4 组合使用构造函数模式和原型模式 定义类 

function School(name,address){
    this.name = name;
    this.address = address;
    this.studens = []; //每个学校的学生不同所以不用共享

    if (typeof(this.getStuNums) != 'function') { //通过判断来创建共享的方法是比较完美的创建原型链共享属性        
        School.prototype.getStuNums = function (){
            return this.studens.length;
        };
    }
}

/*
School.prototype = {
    constructor:School,
    getStuNums:function (){
        return this.studens.length;
    }
};
*/

var sch1 = new School('广州一中','广州天河');
sch1.studens.push('Lee','john');
console.log('sch1.getStuNums',sch1.getStuNums());
var sch2 = new School();